<!--
  存储功能演示页面
  
  展示Electron中各种存储功能：
  - localStorage & sessionStorage
  - IndexedDB
  - SQLite数据库
  - 文件存储
  - 缓存管理
  - 数据同步
-->

<template>
  <div class="storage-features-page">
    <!-- 页面标题 -->
    <div class="header">
      <h2>💾 存储功能演示</h2>
      <p class="subtitle">展示 Electron 中各种数据存储和管理功能</p>
    </div>

    <!-- 功能分组 -->
    <div class="demo-sections">
      
      <!-- 1. Local & Session Storage -->
      <div class="demo-section">
        <h3>📦 本地存储 (localStorage & sessionStorage)</h3>
        <p class="description">Web标准的客户端存储API演示</p>
        
        <div class="storage-tabs">
          <button 
            v-for="tab in storageTabs" 
            :key="tab.key"
            @click="activeStorageTab = tab.key"
            :class="['tab-btn', { active: activeStorageTab === tab.key }]"
          >
            {{ tab.label }}
          </button>
        </div>

        <div class="storage-content">
          <div class="controls">
            <div class="form-row">
              <input 
                v-model="webStorage.key" 
                placeholder="键名"
                class="storage-input"
              >
              <input 
                v-model="webStorage.value" 
                placeholder="值"
                class="storage-input"
              >
              <button @click="setWebStorageItem" class="btn btn-primary">存储</button>
              <button @click="getWebStorageItem" class="btn btn-secondary">获取</button>
              <button @click="removeWebStorageItem" class="btn btn-danger">删除</button>
            </div>
            <div class="form-row">
              <button @click="clearWebStorage" class="btn btn-warning">清空</button>
              <button @click="exportWebStorage" class="btn btn-success">导出</button>
              <button @click="importWebStorage" class="btn btn-info">导入</button>
            </div>
          </div>

          <div class="storage-display">
            <h4>{{ activeStorageTab === 'local' ? 'localStorage' : 'sessionStorage' }} 内容：</h4>
            <div class="storage-list">
              <div v-if="currentStorageItems.length === 0" class="empty-state">
                暂无存储数据
              </div>
              <div v-else>
                <div v-for="(item, index) in currentStorageItems" :key="index" class="storage-item">
                  <div class="item-key">{{ item.key }}</div>
                  <div class="item-value" :title="item.value">{{ truncateText(item.value, 50) }}</div>
                  <div class="item-size">{{ formatSize(item.value.length) }}</div>
                  <div class="item-actions">
                    <button @click="editStorageItem(item)" class="btn btn-sm btn-secondary">编辑</button>
                    <button @click="deleteStorageItem(item.key)" class="btn btn-sm btn-danger">删除</button>
                  </div>
                </div>
              </div>
            </div>
            <div class="storage-stats">
              <span>总条目: {{ currentStorageItems.length }}</span>
              <span>预估大小: {{ getTotalStorageSize() }}</span>
            </div>
          </div>
        </div>
      </div>

      <!-- 2. IndexedDB -->
      <div class="demo-section">
        <h3>🗄️ IndexedDB 数据库</h3>
        <p class="description">浏览器内置的NoSQL数据库，支持事务和索引</p>
        <div class="controls">
          <div class="form-row">
            <select v-model="indexedDB.selectedStore" class="store-select">
              <option value="">选择对象存储</option>
              <option v-for="store in indexedDB.stores" :key="store" :value="store">
                {{ store }}
              </option>
            </select>
            <button @click="createObjectStore" class="btn btn-primary">创建存储</button>
            <button @click="deleteObjectStore" class="btn btn-danger" :disabled="!indexedDB.selectedStore">
              删除存储
            </button>
          </div>
          
          <div class="form-row" v-if="indexedDB.selectedStore">
            <input 
              v-model="indexedDB.key" 
              placeholder="主键"
              class="idb-input"
            >
            <textarea 
              v-model="indexedDB.data" 
              placeholder="数据 (JSON格式)"
              class="idb-textarea"
            ></textarea>
            <button @click="addIndexedDBItem" class="btn btn-success">添加</button>
            <button @click="getIndexedDBItem" class="btn btn-secondary">获取</button>
            <button @click="updateIndexedDBItem" class="btn btn-warning">更新</button>
            <button @click="deleteIndexedDBItem" class="btn btn-danger">删除</button>
          </div>
        </div>

        <div class="indexeddb-display">
          <h4>数据库信息：</h4>
          <div class="db-info">
            <p>数据库名: {{ indexedDB.dbName }}</p>
            <p>版本: {{ indexedDB.version }}</p>
            <p>对象存储数量: {{ indexedDB.stores.length }}</p>
          </div>

          <div v-if="indexedDB.selectedStore" class="store-content">
            <h4>{{ indexedDB.selectedStore }} 存储内容：</h4>
            <div class="data-list">
              <div v-if="indexedDB.items.length === 0" class="empty-state">
                暂无数据
              </div>
              <div v-else>
                <div v-for="(item, index) in indexedDB.items" :key="index" class="data-item">
                  <div class="data-key">{{ item.key }}</div>
                  <div class="data-value">
                    <pre>{{ JSON.stringify(item.value, null, 2) }}</pre>
                  </div>
                  <div class="data-actions">
                    <button @click="editIndexedDBItem(item)" class="btn btn-sm btn-secondary">编辑</button>
                    <button @click="deleteIndexedDBRecord(item.key)" class="btn btn-sm btn-danger">删除</button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 3. SQLite 数据库 -->
      <div class="demo-section">
        <h3>🗃️ SQLite 数据库</h3>
        <p class="description">轻量级关系型数据库，支持SQL查询</p>
        <div class="controls">
          <div class="form-row">
            <input 
              v-model="sqlite.dbPath" 
              placeholder="数据库文件路径"
              class="db-path-input"
            >
            <button @click="connectSQLite" class="btn btn-primary" :disabled="sqlite.connected">
              {{ sqlite.connected ? '已连接' : '连接数据库' }}
            </button>
            <button @click="disconnectSQLite" class="btn btn-secondary" :disabled="!sqlite.connected">
              断开连接
            </button>
            <button @click="createSampleTables" class="btn btn-success" :disabled="!sqlite.connected">
              创建示例表
            </button>
          </div>
          
          <div class="sql-editor">
            <h4>SQL 查询编辑器：</h4>
            <div class="editor-toolbar">
              <button 
                v-for="query in sqliteQueries" 
                :key="query.name"
                @click="sqlite.query = query.sql"
                class="btn btn-sm btn-secondary"
              >
                {{ query.name }}
              </button>
            </div>
            <textarea 
              v-model="sqlite.query" 
              placeholder="输入SQL查询语句..."
              class="sql-textarea"
            ></textarea>
            <div class="editor-actions">
              <button @click="executeSQLQuery" class="btn btn-primary" :disabled="!sqlite.connected">
                执行查询
              </button>
              <button @click="formatSQL" class="btn btn-secondary">格式化SQL</button>
              <button @click="clearSQLEditor" class="btn btn-warning">清空编辑器</button>
            </div>
          </div>
        </div>

        <div class="sql-results">
          <h4>查询结果：</h4>
          <div v-if="sqlite.results.length === 0 && !sqlite.error" class="empty-state">
            暂无查询结果
          </div>
          <div v-else-if="sqlite.error" class="error-display">
            <strong>错误:</strong> {{ sqlite.error }}
          </div>
          <div v-else class="results-table">
            <div class="table-info">
              <span>返回 {{ sqlite.results.length }} 行结果</span>
              <span>执行时间: {{ sqlite.executeTime }}ms</span>
            </div>
            <div class="table-container">
              <table>
                <thead>
                  <tr>
                    <th v-for="column in sqlite.columns" :key="column">{{ column }}</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="(row, index) in sqlite.results" :key="index">
                    <td v-for="column in sqlite.columns" :key="column">
                      {{ row[column] }}
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>

      <!-- 4. 文件存储 -->
      <div class="demo-section">
        <h3>📁 文件存储</h3>
        <p class="description">直接文件读写操作，支持JSON、文本、二进制等格式</p>
        <div class="controls">
          <div class="form-row">
            <input 
              v-model="fileStorage.filename" 
              placeholder="文件名"
              class="filename-input"
            >
            <select v-model="fileStorage.format" class="format-select">
              <option value="json">JSON</option>
              <option value="text">文本</option>
              <option value="csv">CSV</option>
              <option value="xml">XML</option>
            </select>
            <button @click="chooseFile" class="btn btn-secondary">选择文件</button>
          </div>
          
          <div class="file-editor">
            <h4>文件内容编辑器：</h4>
            <div class="editor-toolbar">
              <button @click="loadFile" class="btn btn-primary">加载文件</button>
              <button @click="saveFile" class="btn btn-success">保存文件</button>
              <button @click="saveAsFile" class="btn btn-info">另存为</button>
              <button @click="clearFileContent" class="btn btn-warning">清空内容</button>
            </div>
            <textarea 
              v-model="fileStorage.content" 
              placeholder="文件内容..."
              class="file-textarea"
            ></textarea>
          </div>
        </div>

        <div class="file-info">
          <h4>文件信息：</h4>
          <div v-if="fileStorage.currentFile" class="file-details">
            <div class="info-grid">
              <div class="info-item">
                <span class="label">文件名:</span>
                <span class="value">{{ fileStorage.currentFile.name }}</span>
              </div>
              <div class="info-item">
                <span class="label">文件大小:</span>
                <span class="value">{{ formatFileSize(fileStorage.currentFile.size) }}</span>
              </div>
              <div class="info-item">
                <span class="label">修改时间:</span>
                <span class="value">{{ new Date(fileStorage.currentFile.lastModified).toLocaleString() }}</span>
              </div>
              <div class="info-item">
                <span class="label">文件类型:</span>
                <span class="value">{{ fileStorage.currentFile.type || '未知' }}</span>
              </div>
            </div>
          </div>
          <div v-else class="no-file">
            未选择文件
          </div>
        </div>
      </div>

      <!-- 5. 缓存管理 -->
      <div class="demo-section">
        <h3>🚀 缓存管理</h3>
        <p class="description">高效的数据缓存系统，支持过期时间和LRU策略</p>
        <div class="controls">
          <div class="form-row">
            <input 
              v-model="cache.key" 
              placeholder="缓存键"
              class="cache-input"
            >
            <input 
              v-model="cache.value" 
              placeholder="缓存值"
              class="cache-input"
            >
            <input 
              v-model="cache.ttl" 
              placeholder="过期时间(秒)"
              type="number"
              class="ttl-input"
            >
            <button @click="setCacheItem" class="btn btn-primary">设置缓存</button>
            <button @click="getCacheItem" class="btn btn-secondary">获取缓存</button>
          </div>
          
          <div class="form-row">
            <button @click="clearExpiredCache" class="btn btn-warning">清理过期</button>
            <button @click="clearAllCache" class="btn btn-danger">清空缓存</button>
            <button @click="exportCache" class="btn btn-success">导出缓存</button>
            <select v-model="cache.strategy" class="strategy-select">
              <option value="lru">LRU策略</option>
              <option value="fifo">FIFO策略</option>
              <option value="ttl">TTL策略</option>
            </select>
          </div>
        </div>

        <div class="cache-display">
          <div class="cache-stats">
            <div class="stat-card">
              <h5>缓存统计</h5>
              <div class="stat-grid">
                <div class="stat-item">
                  <span class="stat-label">总数量:</span>
                  <span class="stat-value">{{ cache.items.length }}</span>
                </div>
                <div class="stat-item">
                  <span class="stat-label">命中率:</span>
                  <span class="stat-value">{{ cache.hitRate }}%</span>
                </div>
                <div class="stat-item">
                  <span class="stat-label">过期数量:</span>
                  <span class="stat-value">{{ getExpiredCacheCount() }}</span>
                </div>
                <div class="stat-item">
                  <span class="stat-label">内存占用:</span>
                  <span class="stat-value">{{ getCacheMemoryUsage() }}</span>
                </div>
              </div>
            </div>
          </div>

          <div class="cache-list">
            <h4>缓存条目：</h4>
            <div v-if="cache.items.length === 0" class="empty-state">
              暂无缓存数据
            </div>
            <div v-else>
              <div v-for="(item, index) in cache.items" :key="index" :class="['cache-item', { expired: isCacheExpired(item) }]">
                <div class="cache-key">{{ item.key }}</div>
                <div class="cache-value" :title="item.value">{{ truncateText(item.value, 30) }}</div>
                <div class="cache-meta">
                  <span class="cache-ttl">
                    {{ item.expiresAt ? `过期: ${new Date(item.expiresAt).toLocaleString()}` : '永不过期' }}
                  </span>
                  <span class="cache-size">{{ formatSize(JSON.stringify(item.value).length) }}</span>
                </div>
                <div class="cache-actions">
                  <button @click="refreshCacheItem(item)" class="btn btn-sm btn-success">刷新</button>
                  <button @click="deleteCacheItem(item.key)" class="btn btn-sm btn-danger">删除</button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 6. 数据同步 -->
      <div class="demo-section">
        <h3>🔄 数据同步</h3>
        <p class="description">多端数据同步，支持冲突解决和增量更新</p>
        <div class="controls">
          <div class="form-row">
            <input 
              v-model="sync.serverUrl" 
              placeholder="同步服务器URL"
              class="server-input"
            >
            <button @click="connectSyncServer" class="btn btn-primary" :disabled="sync.connected">
              {{ sync.connected ? '已连接' : '连接服务器' }}
            </button>
            <button @click="disconnectSyncServer" class="btn btn-secondary" :disabled="!sync.connected">
              断开连接
            </button>
          </div>
          
          <div class="form-row" v-if="sync.connected">
            <button @click="syncToServer" class="btn btn-success" :disabled="sync.syncing">
              {{ sync.syncing ? '同步中...' : '推送到服务器' }}
            </button>
            <button @click="syncFromServer" class="btn btn-info" :disabled="sync.syncing">
              从服务器拉取
            </button>
            <button @click="autoSyncToggle" :class="['btn', sync.autoSync ? 'btn-warning' : 'btn-primary']">
              {{ sync.autoSync ? '停止自动同步' : '启动自动同步' }}
            </button>
          </div>
        </div>

        <div class="sync-display">
          <div class="sync-status">
            <div class="status-indicator">
              <span :class="['status-dot', sync.connected ? 'connected' : 'disconnected']"></span>
              <span class="status-text">
                {{ sync.connected ? '已连接到同步服务器' : '未连接' }}
              </span>
            </div>
            <div v-if="sync.lastSyncTime" class="last-sync">
              上次同步: {{ new Date(sync.lastSyncTime).toLocaleString() }}
            </div>
          </div>

          <div class="sync-conflicts" v-if="sync.conflicts.length > 0">
            <h4>同步冲突：</h4>
            <div v-for="(conflict, index) in sync.conflicts" :key="index" class="conflict-item">
              <div class="conflict-header">
                <span class="conflict-key">{{ conflict.key }}</span>
                <span class="conflict-type">{{ conflict.type }}</span>
              </div>
              <div class="conflict-data">
                <div class="local-data">
                  <h5>本地数据:</h5>
                  <pre>{{ JSON.stringify(conflict.localValue, null, 2) }}</pre>
                </div>
                <div class="remote-data">
                  <h5>远程数据:</h5>
                  <pre>{{ JSON.stringify(conflict.remoteValue, null, 2) }}</pre>
                </div>
              </div>
              <div class="conflict-actions">
                <button @click="resolveConflict(index, 'local')" class="btn btn-sm btn-primary">使用本地</button>
                <button @click="resolveConflict(index, 'remote')" class="btn btn-sm btn-success">使用远程</button>
                <button @click="resolveConflict(index, 'merge')" class="btn btn-sm btn-info">合并</button>
              </div>
            </div>
          </div>

          <div class="sync-log">
            <h4>同步日志：</h4>
            <div class="log-container">
              <div v-if="sync.logs.length === 0" class="empty-state">
                暂无同步记录
              </div>
              <div v-else>
                <div v-for="(log, index) in sync.logs" :key="index" :class="['log-item', log.type]">
                  <span class="log-time">{{ log.timestamp }}</span>
                  <span class="log-type">{{ log.type }}</span>
                  <span class="log-message">{{ log.message }}</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

    </div>

    <!-- 消息提示 -->
    <div v-if="message.text" :class="['message', message.type]">
      {{ message.text }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'

// Web Storage相关
const storageTabs = [
  { key: 'local', label: 'localStorage' },
  { key: 'session', label: 'sessionStorage' }
]

const activeStorageTab = ref('local')

const webStorage = reactive({
  key: '',
  value: ''
})

const localStorageItems = ref<any[]>([])
const sessionStorageItems = ref<any[]>([])

// IndexedDB相关
const indexedDB = reactive({
  dbName: 'ElectronDemo',
  version: 1,
  stores: ['users', 'products', 'orders'],
  selectedStore: '',
  key: '',
  data: '{}',
  items: [] as any[]
})

// SQLite相关
const sqlite = reactive({
  dbPath: './demo.db',
  connected: false,
  query: 'SELECT * FROM users LIMIT 10;',
  results: [] as any[],
  columns: [] as string[],
  error: '',
  executeTime: 0
})

const sqliteQueries = [
  { name: '查询用户', sql: 'SELECT * FROM users LIMIT 10;' },
  { name: '插入用户', sql: "INSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');" },
  { name: '更新用户', sql: "UPDATE users SET email = 'newemail@example.com' WHERE id = 1;" },
  { name: '删除用户', sql: 'DELETE FROM users WHERE id = 1;' },
  { name: '创建表', sql: 'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT);' }
]

// 文件存储相关
const fileStorage = reactive({
  filename: 'data.json',
  format: 'json',
  content: '',
  currentFile: null as File | null
})

// 缓存管理相关
const cache = reactive({
  key: '',
  value: '',
  ttl: 300,
  strategy: 'lru',
  items: [] as any[],
  hitCount: 0,
  missCount: 0
})

// 数据同步相关
const sync = reactive({
  serverUrl: 'ws://localhost:3001/sync',
  connected: false,
  syncing: false,
  autoSync: false,
  lastSyncTime: null as number | null,
  conflicts: [] as any[],
  logs: [] as any[]
})

let syncInterval: number | null = null

// 消息提示
const message = reactive({
  text: '',
  type: 'info'
})

/**
 * 计算属性：当前存储项目
 */
const currentStorageItems = computed(() => {
  return activeStorageTab.value === 'local' ? localStorageItems.value : sessionStorageItems.value
})

/**
 * 计算属性：缓存命中率
 */
const cache_hitRate = computed(() => {
  const total = cache.hitCount + cache.missCount
  return total === 0 ? 0 : Math.round((cache.hitCount / total) * 100)
})

// 修正cache对象的hitRate属性
Object.defineProperty(cache, 'hitRate', {
  get() {
    const total = cache.hitCount + cache.missCount
    return total === 0 ? 0 : Math.round((cache.hitCount / total) * 100)
  }
})

/**
 * 设置Web存储项
 */
const setWebStorageItem = () => {
  if (!webStorage.key.trim()) {
    showMessage('请输入键名', 'warning')
    return
  }

  const storage = activeStorageTab.value === 'local' ? localStorage : sessionStorage
  storage.setItem(webStorage.key, webStorage.value)
  
  refreshWebStorage()
  showMessage('存储成功', 'success')
  
  // 清空输入
  webStorage.key = ''
  webStorage.value = ''
}

/**
 * 获取Web存储项
 */
const getWebStorageItem = () => {
  if (!webStorage.key.trim()) {
    showMessage('请输入键名', 'warning')
    return
  }

  const storage = activeStorageTab.value === 'local' ? localStorage : sessionStorage
  const value = storage.getItem(webStorage.key)
  
  if (value !== null) {
    webStorage.value = value
    showMessage('获取成功', 'success')
  } else {
    showMessage('未找到该键', 'warning')
  }
}

/**
 * 移除Web存储项
 */
const removeWebStorageItem = () => {
  if (!webStorage.key.trim()) {
    showMessage('请输入键名', 'warning')
    return
  }

  const storage = activeStorageTab.value === 'local' ? localStorage : sessionStorage
  storage.removeItem(webStorage.key)
  
  refreshWebStorage()
  showMessage('删除成功', 'info')
}

/**
 * 清空Web存储
 */
const clearWebStorage = () => {
  const storage = activeStorageTab.value === 'local' ? localStorage : sessionStorage
  storage.clear()
  
  refreshWebStorage()
  showMessage('清空成功', 'info')
}

/**
 * 导出Web存储
 */
const exportWebStorage = () => {
  const storage = activeStorageTab.value === 'local' ? localStorage : sessionStorage
  const data: any = {}
  
  for (let i = 0; i < storage.length; i++) {
    const key = storage.key(i)
    if (key) {
      data[key] = storage.getItem(key)
    }
  }

  const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `${activeStorageTab.value}Storage-${Date.now()}.json`
  a.click()
  URL.revokeObjectURL(url)

  showMessage('导出成功', 'success')
}

/**
 * 导入Web存储
 */
const importWebStorage = () => {
  const input = document.createElement('input')
  input.type = 'file'
  input.accept = '.json'
  
  input.onchange = (e) => {
    const file = (e.target as HTMLInputElement).files?.[0]
    if (!file) return

    const reader = new FileReader()
    reader.onload = (e) => {
      try {
        const data = JSON.parse(e.target?.result as string)
        const storage = activeStorageTab.value === 'local' ? localStorage : sessionStorage
        
        Object.entries(data).forEach(([key, value]) => {
          storage.setItem(key, value as string)
        })
        
        refreshWebStorage()
        showMessage('导入成功', 'success')
      } catch (error) {
        showMessage('导入失败：文件格式错误', 'error')
      }
    }
    reader.readAsText(file)
  }
  
  input.click()
}

/**
 * 刷新Web存储显示
 */
const refreshWebStorage = () => {
  const refreshStorage = (storage: Storage, items: any[]) => {
    items.length = 0
    for (let i = 0; i < storage.length; i++) {
      const key = storage.key(i)
      if (key) {
        items.push({
          key,
          value: storage.getItem(key) || ''
        })
      }
    }
  }

  refreshStorage(localStorage, localStorageItems.value)
  refreshStorage(sessionStorage, sessionStorageItems.value)
}

/**
 * 编辑存储项
 */
const editStorageItem = (item: any) => {
  webStorage.key = item.key
  webStorage.value = item.value
}

/**
 * 删除存储项
 */
const deleteStorageItem = (key: string) => {
  const storage = activeStorageTab.value === 'local' ? localStorage : sessionStorage
  storage.removeItem(key)
  refreshWebStorage()
  showMessage('删除成功', 'info')
}

/**
 * 获取存储总大小
 */
const getTotalStorageSize = (): string => {
  const items = currentStorageItems.value
  const totalSize = items.reduce((sum, item) => sum + item.key.length + item.value.length, 0)
  return formatSize(totalSize)
}

/**
 * 创建IndexedDB对象存储
 */
const createObjectStore = () => {
  const storeName = prompt('请输入对象存储名称:')
  if (!storeName || indexedDB.stores.includes(storeName)) {
    showMessage('存储名称无效或已存在', 'warning')
    return
  }

  // 模拟创建对象存储
  indexedDB.stores.push(storeName)
  showMessage(`对象存储 "${storeName}" 创建成功`, 'success')
}

/**
 * 删除IndexedDB对象存储
 */
const deleteObjectStore = () => {
  if (!indexedDB.selectedStore) return

  if (confirm(`确定要删除对象存储 "${indexedDB.selectedStore}" 吗？`)) {
    indexedDB.stores = indexedDB.stores.filter(store => store !== indexedDB.selectedStore)
    indexedDB.selectedStore = ''
    indexedDB.items = []
    showMessage('对象存储删除成功', 'info')
  }
}

/**
 * 添加IndexedDB项
 */
const addIndexedDBItem = () => {
  if (!indexedDB.selectedStore || !indexedDB.key.trim()) {
    showMessage('请选择对象存储并输入主键', 'warning')
    return
  }

  try {
    const data = JSON.parse(indexedDB.data)
    indexedDB.items.push({
      key: indexedDB.key,
      value: data
    })
    showMessage('数据添加成功', 'success')
    indexedDB.key = ''
    indexedDB.data = '{}'
  } catch (error) {
    showMessage('数据格式错误', 'error')
  }
}

/**
 * 获取IndexedDB项
 */
const getIndexedDBItem = () => {
  if (!indexedDB.key.trim()) {
    showMessage('请输入主键', 'warning')
    return
  }

  const item = indexedDB.items.find(item => item.key === indexedDB.key)
  if (item) {
    indexedDB.data = JSON.stringify(item.value, null, 2)
    showMessage('数据获取成功', 'success')
  } else {
    showMessage('未找到该数据', 'warning')
  }
}

/**
 * 更新IndexedDB项
 */
const updateIndexedDBItem = () => {
  if (!indexedDB.key.trim()) {
    showMessage('请输入主键', 'warning')
    return
  }

  try {
    const data = JSON.parse(indexedDB.data)
    const index = indexedDB.items.findIndex(item => item.key === indexedDB.key)
    
    if (index !== -1) {
      indexedDB.items[index].value = data
      showMessage('数据更新成功', 'success')
    } else {
      showMessage('未找到该数据', 'warning')
    }
  } catch (error) {
    showMessage('数据格式错误', 'error')
  }
}

/**
 * 删除IndexedDB项
 */
const deleteIndexedDBItem = () => {
  if (!indexedDB.key.trim()) {
    showMessage('请输入主键', 'warning')
    return
  }

  indexedDB.items = indexedDB.items.filter(item => item.key !== indexedDB.key)
  showMessage('数据删除成功', 'info')
}

/**
 * 编辑IndexedDB项
 */
const editIndexedDBItem = (item: any) => {
  indexedDB.key = item.key
  indexedDB.data = JSON.stringify(item.value, null, 2)
}

/**
 * 删除IndexedDB记录
 */
const deleteIndexedDBRecord = (key: string) => {
  indexedDB.items = indexedDB.items.filter(item => item.key !== key)
  showMessage('记录删除成功', 'info')
}

/**
 * 连接SQLite数据库
 */
const connectSQLite = async () => {
  try {
    // 这里应该调用Electron的API连接SQLite
    // await window.api.sqlite.connect(sqlite.dbPath)
    
    sqlite.connected = true
    showMessage('数据库连接成功', 'success')
  } catch (error) {
    showMessage('数据库连接失败: ' + error, 'error')
  }
}

/**
 * 断开SQLite连接
 */
const disconnectSQLite = async () => {
  try {
    // await window.api.sqlite.disconnect()
    
    sqlite.connected = false
    sqlite.results = []
    sqlite.columns = []
    showMessage('数据库连接已断开', 'info')
  } catch (error) {
    showMessage('断开连接失败: ' + error, 'error')
  }
}

/**
 * 创建示例表
 */
const createSampleTables = async () => {
  const queries = [
    'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP);',
    'CREATE TABLE IF NOT EXISTS products (id INTEGER PRIMARY KEY, name TEXT, price REAL, category TEXT);',
    "INSERT OR IGNORE INTO users (id, name, email) VALUES (1, '张三', 'zhangsan@example.com');",
    "INSERT OR IGNORE INTO users (id, name, email) VALUES (2, '李四', 'lisi@example.com');",
    "INSERT OR IGNORE INTO products (id, name, price, category) VALUES (1, '笔记本电脑', 5999.99, '电子产品');"
  ]

  try {
    // 模拟执行创建表的SQL
    showMessage('示例表创建成功', 'success')
  } catch (error) {
    showMessage('创建示例表失败: ' + error, 'error')
  }
}

/**
 * 执行SQL查询
 */
const executeSQLQuery = async () => {
  if (!sqlite.query.trim()) {
    showMessage('请输入SQL查询语句', 'warning')
    return
  }

  const startTime = Date.now()
  
  try {
    // 这里应该调用Electron的API执行SQL
    // const result = await window.api.sqlite.execute(sqlite.query)
    
    // 模拟查询结果
    const mockResult = [
      { id: 1, name: '张三', email: 'zhangsan@example.com', created_at: '2023-01-01 10:00:00' },
      { id: 2, name: '李四', email: 'lisi@example.com', created_at: '2023-01-02 11:00:00' }
    ]
    
    sqlite.results = mockResult
    sqlite.columns = mockResult.length > 0 ? Object.keys(mockResult[0]) : []
    sqlite.error = ''
    sqlite.executeTime = Date.now() - startTime
    
    showMessage('查询执行成功', 'success')
  } catch (error) {
    sqlite.error = error.toString()
    sqlite.results = []
    sqlite.columns = []
    showMessage('查询执行失败', 'error')
  }
}

/**
 * 格式化SQL
 */
const formatSQL = () => {
  // 简单的SQL格式化
  sqlite.query = sqlite.query
    .replace(/\s+/g, ' ')
    .replace(/,/g, ',\n  ')
    .replace(/FROM/gi, '\nFROM')
    .replace(/WHERE/gi, '\nWHERE')
    .replace(/ORDER BY/gi, '\nORDER BY')
    .replace(/GROUP BY/gi, '\nGROUP BY')
    .trim()
  
  showMessage('SQL格式化完成', 'info')
}

/**
 * 清空SQL编辑器
 */
const clearSQLEditor = () => {
  sqlite.query = ''
  sqlite.results = []
  sqlite.columns = []
  sqlite.error = ''
}

/**
 * 选择文件
 */
const chooseFile = () => {
  const input = document.createElement('input')
  input.type = 'file'
  
  input.onchange = (e) => {
    const file = (e.target as HTMLInputElement).files?.[0]
    if (file) {
      fileStorage.currentFile = file
      fileStorage.filename = file.name
      showMessage('文件选择成功', 'success')
    }
  }
  
  input.click()
}

/**
 * 加载文件
 */
const loadFile = () => {
  if (!fileStorage.currentFile) {
    showMessage('请先选择文件', 'warning')
    return
  }

  const reader = new FileReader()
  reader.onload = (e) => {
    fileStorage.content = e.target?.result as string
    showMessage('文件加载成功', 'success')
  }
  reader.readAsText(fileStorage.currentFile)
}

/**
 * 保存文件
 */
const saveFile = () => {
  if (!fileStorage.content.trim()) {
    showMessage('内容为空', 'warning')
    return
  }

  const blob = new Blob([fileStorage.content], { type: 'text/plain' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = fileStorage.filename
  a.click()
  URL.revokeObjectURL(url)

  showMessage('文件保存成功', 'success')
}

/**
 * 另存为文件
 */
const saveAsFile = () => {
  const filename = prompt('请输入文件名:', fileStorage.filename)
  if (filename) {
    fileStorage.filename = filename
    saveFile()
  }
}

/**
 * 清空文件内容
 */
const clearFileContent = () => {
  fileStorage.content = ''
  showMessage('内容已清空', 'info')
}

/**
 * 设置缓存项
 */
const setCacheItem = () => {
  if (!cache.key.trim()) {
    showMessage('请输入缓存键', 'warning')
    return
  }

  const expiresAt = cache.ttl > 0 ? Date.now() + (cache.ttl * 1000) : null
  
  const existingIndex = cache.items.findIndex(item => item.key === cache.key)
  if (existingIndex !== -1) {
    cache.items[existingIndex] = {
      key: cache.key,
      value: cache.value,
      expiresAt,
      createdAt: Date.now()
    }
  } else {
    cache.items.push({
      key: cache.key,
      value: cache.value,
      expiresAt,
      createdAt: Date.now()
    })
  }

  // 应用缓存策略
  applyCacheStrategy()
  
  showMessage('缓存设置成功', 'success')
  cache.key = ''
  cache.value = ''
}

/**
 * 获取缓存项
 */
const getCacheItem = () => {
  if (!cache.key.trim()) {
    showMessage('请输入缓存键', 'warning')
    return
  }

  const item = cache.items.find(item => item.key === cache.key)
  
  if (!item) {
    cache.missCount++
    showMessage('缓存未命中', 'warning')
    return
  }

  if (item.expiresAt && Date.now() > item.expiresAt) {
    cache.missCount++
    showMessage('缓存已过期', 'warning')
    return
  }

  cache.hitCount++
  cache.value = item.value
  showMessage('缓存命中', 'success')
}

/**
 * 应用缓存策略
 */
const applyCacheStrategy = () => {
  const maxItems = 50

  if (cache.items.length <= maxItems) return

  switch (cache.strategy) {
    case 'lru':
      // LRU: 移除最近最少使用的项
      cache.items.sort((a, b) => (b.lastAccessed || b.createdAt) - (a.lastAccessed || a.createdAt))
      cache.items = cache.items.slice(0, maxItems)
      break
      
    case 'fifo':
      // FIFO: 移除最早创建的项
      cache.items.sort((a, b) => a.createdAt - b.createdAt)
      cache.items = cache.items.slice(-maxItems)
      break
      
    case 'ttl':
      // TTL: 移除已过期的项
      const now = Date.now()
      cache.items = cache.items.filter(item => !item.expiresAt || now < item.expiresAt)
      break
  }
}

/**
 * 清理过期缓存
 */
const clearExpiredCache = () => {
  const now = Date.now()
  const beforeCount = cache.items.length
  
  cache.items = cache.items.filter(item => !item.expiresAt || now < item.expiresAt)
  
  const clearedCount = beforeCount - cache.items.length
  showMessage(`清理了 ${clearedCount} 个过期缓存`, 'info')
}

/**
 * 清空所有缓存
 */
const clearAllCache = () => {
  cache.items = []
  cache.hitCount = 0
  cache.missCount = 0
  showMessage('缓存已清空', 'info')
}

/**
 * 导出缓存
 */
const exportCache = () => {
  const data = {
    items: cache.items,
    stats: {
      hitCount: cache.hitCount,
      missCount: cache.missCount,
      hitRate: cache.hitRate
    },
    exportTime: new Date().toISOString()
  }

  const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `cache-export-${Date.now()}.json`
  a.click()
  URL.revokeObjectURL(url)

  showMessage('缓存导出成功', 'success')
}

/**
 * 获取过期缓存数量
 */
const getExpiredCacheCount = (): number => {
  const now = Date.now()
  return cache.items.filter(item => item.expiresAt && now > item.expiresAt).length
}

/**
 * 获取缓存内存占用
 */
const getCacheMemoryUsage = (): string => {
  const totalSize = cache.items.reduce((sum, item) => {
    return sum + JSON.stringify(item).length
  }, 0)
  return formatSize(totalSize)
}

/**
 * 判断缓存是否过期
 */
const isCacheExpired = (item: any): boolean => {
  return item.expiresAt && Date.now() > item.expiresAt
}

/**
 * 刷新缓存项
 */
const refreshCacheItem = (item: any) => {
  const ttl = cache.ttl || 300
  item.expiresAt = Date.now() + (ttl * 1000)
  item.lastAccessed = Date.now()
  showMessage('缓存已刷新', 'success')
}

/**
 * 删除缓存项
 */
const deleteCacheItem = (key: string) => {
  cache.items = cache.items.filter(item => item.key !== key)
  showMessage('缓存删除成功', 'info')
}

/**
 * 连接同步服务器
 */
const connectSyncServer = () => {
  if (!sync.serverUrl.trim()) {
    showMessage('请输入服务器URL', 'warning')
    return
  }

  // 模拟连接
  sync.connected = true
  addSyncLog('info', '已连接到同步服务器')
  showMessage('连接成功', 'success')
}

/**
 * 断开同步服务器
 */
const disconnectSyncServer = () => {
  sync.connected = false
  sync.autoSync = false
  
  if (syncInterval) {
    clearInterval(syncInterval)
    syncInterval = null
  }
  
  addSyncLog('info', '已断开同步服务器连接')
  showMessage('连接已断开', 'info')
}

/**
 * 同步到服务器
 */
const syncToServer = async () => {
  if (!sync.connected) return

  sync.syncing = true
  addSyncLog('info', '开始推送数据到服务器...')

  try {
    // 模拟同步过程
    await new Promise(resolve => setTimeout(resolve, 2000))
    
    sync.lastSyncTime = Date.now()
    addSyncLog('success', '数据推送成功')
    showMessage('同步到服务器成功', 'success')
  } catch (error) {
    addSyncLog('error', '数据推送失败: ' + error)
    showMessage('同步失败', 'error')
  } finally {
    sync.syncing = false
  }
}

/**
 * 从服务器同步
 */
const syncFromServer = async () => {
  if (!sync.connected) return

  sync.syncing = true
  addSyncLog('info', '开始从服务器拉取数据...')

  try {
    // 模拟同步过程和冲突检测
    await new Promise(resolve => setTimeout(resolve, 2000))
    
    // 模拟冲突
    const hasConflicts = Math.random() > 0.7
    if (hasConflicts) {
      sync.conflicts.push({
        key: 'user_preference',
        type: 'update',
        localValue: { theme: 'dark', language: 'zh' },
        remoteValue: { theme: 'light', language: 'en' }
      })
      addSyncLog('warning', '检测到同步冲突，需要手动解决')
    }
    
    sync.lastSyncTime = Date.now()
    addSyncLog('success', '数据拉取成功')
    showMessage('从服务器同步成功', 'success')
  } catch (error) {
    addSyncLog('error', '数据拉取失败: ' + error)
    showMessage('同步失败', 'error')
  } finally {
    sync.syncing = false
  }
}

/**
 * 切换自动同步
 */
const autoSyncToggle = () => {
  sync.autoSync = !sync.autoSync
  
  if (sync.autoSync) {
    syncInterval = setInterval(() => {
      if (sync.connected && !sync.syncing) {
        syncFromServer()
      }
    }, 30000) // 30秒同步一次
    
    addSyncLog('info', '自动同步已启动')
    showMessage('自动同步已启动', 'success')
  } else {
    if (syncInterval) {
      clearInterval(syncInterval)
      syncInterval = null
    }
    
    addSyncLog('info', '自动同步已停止')
    showMessage('自动同步已停止', 'info')
  }
}

/**
 * 解决同步冲突
 */
const resolveConflict = (index: number, resolution: 'local' | 'remote' | 'merge') => {
  const conflict = sync.conflicts[index]
  
  switch (resolution) {
    case 'local':
      addSyncLog('info', `冲突已解决：使用本地数据 (${conflict.key})`)
      break
    case 'remote':
      addSyncLog('info', `冲突已解决：使用远程数据 (${conflict.key})`)
      break
    case 'merge':
      addSyncLog('info', `冲突已解决：合并数据 (${conflict.key})`)
      break
  }
  
  sync.conflicts.splice(index, 1)
  showMessage('冲突解决成功', 'success')
}

/**
 * 添加同步日志
 */
const addSyncLog = (type: 'info' | 'success' | 'warning' | 'error', message: string) => {
  sync.logs.unshift({
    timestamp: new Date().toLocaleTimeString(),
    type,
    message
  })

  // 限制日志数量
  if (sync.logs.length > 50) {
    sync.logs = sync.logs.slice(0, 50)
  }
}

/**
 * 工具函数：截断文本
 */
const truncateText = (text: string, maxLength: number): string => {
  if (text.length <= maxLength) return text
  return text.substring(0, maxLength) + '...'
}

/**
 * 工具函数：格式化大小
 */
const formatSize = (bytes: number): string => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

/**
 * 工具函数：格式化文件大小
 */
const formatFileSize = (bytes: number): string => {
  return formatSize(bytes)
}

/**
 * 显示消息提示
 */
const showMessage = (text: string, type: 'success' | 'error' | 'warning' | 'info' = 'info') => {
  message.text = text
  message.type = type
  
  setTimeout(() => {
    message.text = ''
  }, 3000)
}

// 生命周期
onMounted(() => {
  showMessage('存储功能演示已就绪', 'success')
  
  // 初始化Web存储显示
  refreshWebStorage()
  
  // 模拟一些缓存数据
  cache.items = [
    {
      key: 'user_config',
      value: '{"theme":"dark","language":"zh"}',
      expiresAt: Date.now() + 300000,
      createdAt: Date.now() - 60000
    },
    {
      key: 'api_token',
      value: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
      expiresAt: Date.now() + 3600000,
      createdAt: Date.now() - 120000
    }
  ]
})

onUnmounted(() => {
  // 清理资源
  if (syncInterval) {
    clearInterval(syncInterval)
    syncInterval = null
  }
  
  console.log('存储功能演示组件已卸载')
})
</script>

<style scoped>
.storage-features-page {
  min-height: 100vh;
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  box-sizing: border-box;
}

.header {
  text-align: center;
  margin-bottom: 40px;
}

.header h2 {
  color: var(--text-primary, #2c3e50);
  margin: 0;
  font-size: 2.2em;
}

.subtitle {
  color: var(--text-secondary, #7f8c8d);
  margin: 5px 0 0 0;
  font-size: 1.1em;
}

.demo-sections {
  display: grid;
  gap: 30px;
}

.demo-section {
  background: var(--card-bg, #f8f9fa);
  border-radius: 12px;
  padding: 25px;
  border-left: 4px solid var(--primary-color, #3498db);
  box-shadow: var(--shadow-sm, 0 2px 10px rgba(0, 0, 0, 0.1));
  border: 1px solid var(--card-border, transparent);
}

.demo-section h3 {
  margin: 0 0 10px 0;
  color: var(--text-primary, #2c3e50);
  font-size: 1.3em;
}

.description {
  color: var(--text-secondary, #666);
  margin: 0 0 20px 0;
  font-size: 14px;
  line-height: 1.5;
}

.controls {
  margin-bottom: 20px;
}

.form-row {
  display: flex;
  gap: 15px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 15px;
}

.btn {
  padding: 10px 20px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.3s ease;
  min-width: 100px;
}

.btn:hover:not(:disabled) {
  transform: translateY(-2px);
  box-shadow: var(--shadow, 0 4px 8px rgba(0, 0, 0, 0.2));
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

.btn-primary {
  background: linear-gradient(45deg, var(--primary-color, #3498db), var(--primary-hover, #2980b9));
  color: var(--text-inverse, white);
}

.btn-secondary {
  background: linear-gradient(45deg, var(--text-secondary, #95a5a6), #7f8c8d);
  color: var(--text-inverse, white);
}

.btn-success {
  background: linear-gradient(45deg, var(--success-color, #2ecc71), var(--success-hover, #27ae60));
  color: var(--text-inverse, white);
}

.btn-danger {
  background: linear-gradient(45deg, var(--error-color, #e74c3c), var(--error-hover, #c0392b));
  color: var(--text-inverse, white);
}

.btn-warning {
  background: linear-gradient(45deg, var(--warning-color, #f39c12), var(--warning-hover, #e67e22));
  color: var(--text-inverse, white);
}

.btn-info {
  background: linear-gradient(45deg, var(--info-color, #3498db), var(--info-hover, #2980b9));
  color: var(--text-inverse, white);
}

.btn-sm {
  padding: 5px 10px;
  font-size: 12px;
  min-width: 60px;
}

/* Storage Tabs */
.storage-tabs {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.tab-btn {
  padding: 10px 20px;
  border: none;
  border-radius: 6px 6px 0 0;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  background: var(--bg-tertiary, #e9ecef);
  color: var(--text-secondary, #666);
  transition: all 0.3s ease;
}

.tab-btn:hover {
  background: var(--bg-hover, #dee2e6);
}

.tab-btn.active {
  background: var(--primary-color, #3498db);
  color: var(--text-inverse, white);
}

/* Input styles */
.storage-input, .idb-input, .cache-input, .server-input, .filename-input, .db-path-input {
  flex: 1;
  min-width: 150px;
  padding: 10px 15px;
  border: 2px solid var(--border-color, #bdc3c7);
  border-radius: 6px;
  background: var(--input-bg, white);
  color: var(--text-primary, #333);
  font-size: 14px;
}

.ttl-input {
  width: 120px;
  padding: 10px 15px;
  border: 2px solid var(--border-color, #bdc3c7);
  border-radius: 6px;
  background: var(--input-bg, white);
  color: var(--text-primary, #333);
  font-size: 14px;
}

.store-select, .format-select, .strategy-select {
  padding: 10px;
  border: 2px solid var(--border-color, #bdc3c7);
  border-radius: 6px;
  background: var(--input-bg, white);
  color: var(--text-primary, #333);
  font-size: 14px;
  min-width: 120px;
}

.idb-textarea, .sql-textarea, .file-textarea {
  width: 100%;
  min-height: 120px;
  padding: 10px 15px;
  border: 2px solid var(--border-color, #bdc3c7);
  border-radius: 6px;
  background: var(--input-bg, white);
  color: var(--text-primary, #333);
  font-size: 14px;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  resize: vertical;
}

.storage-input:focus, .idb-input:focus, .cache-input:focus, .server-input:focus,
.filename-input:focus, .db-path-input:focus, .ttl-input:focus,
.store-select:focus, .format-select:focus, .strategy-select:focus,
.idb-textarea:focus, .sql-textarea:focus, .file-textarea:focus {
  outline: none;
  border-color: var(--primary-color, #3498db);
  box-shadow: var(--input-focus-shadow, 0 0 0 0.2rem rgba(52, 152, 219, 0.25));
}

/* Storage display */
.storage-content {
  background: var(--bg-secondary, white);
  border-radius: 8px;
  padding: 20px;
  border: 1px solid var(--border-color, #ddd);
}

.storage-display h4 {
  color: var(--text-primary, #333);
  margin: 0 0 15px 0;
}

.storage-list, .data-list, .cache-list {
  max-height: 300px;
  overflow-y: auto;
}

.empty-state {
  color: var(--text-muted, #999);
  font-style: italic;
  text-align: center;
  padding: 20px;
  background: var(--bg-tertiary, #f5f5f5);
  border-radius: 6px;
}

.storage-item, .data-item, .cache-item {
  display: grid;
  grid-template-columns: 1fr 2fr auto auto;
  gap: 15px;
  align-items: center;
  padding: 12px;
  margin-bottom: 10px;
  background: var(--bg-tertiary, #f9f9f9);
  border-radius: 6px;
  border: 1px solid var(--border-color, #e0e0e0);
}

.cache-item {
  grid-template-columns: 1fr 1fr 2fr auto;
}

.cache-item.expired {
  opacity: 0.6;
  background: var(--error-light, #ffe6e6);
  border-color: var(--error-color, #e74c3c);
}

.item-key, .data-key, .cache-key {
  font-weight: bold;
  color: var(--text-primary, #333);
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 13px;
}

.item-value, .cache-value {
  color: var(--text-secondary, #666);
  word-break: break-all;
  font-size: 13px;
}

.data-value {
  color: var(--text-secondary, #666);
  font-size: 12px;
}

.data-value pre {
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  background: var(--bg-primary, white);
  padding: 5px;
  border-radius: 4px;
}

.item-size {
  color: var(--text-muted, #999);
  font-size: 12px;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}

.cache-meta {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.cache-ttl, .cache-size {
  color: var(--text-muted, #999);
  font-size: 11px;
}

.item-actions, .data-actions, .cache-actions {
  display: flex;
  gap: 5px;
}

.storage-stats {
  margin-top: 15px;
  padding-top: 15px;
  border-top: 1px solid var(--border-color, #e0e0e0);
  display: flex;
  justify-content: space-between;
  color: var(--text-secondary, #666);
  font-size: 13px;
}

/* IndexedDB styles */
.indexeddb-display {
  margin-top: 20px;
}

.indexeddb-display h4 {
  color: var(--text-primary, #333);
  margin: 0 0 15px 0;
}

.db-info {
  background: var(--bg-tertiary, #f5f5f5);
  border-radius: 6px;
  padding: 15px;
  margin-bottom: 20px;
}

.db-info p {
  margin: 5px 0;
  color: var(--text-primary, #333);
  font-size: 14px;
}

.store-content {
  margin-top: 20px;
}

/* SQLite styles */
.sql-editor {
  margin-top: 20px;
}

.sql-editor h4 {
  color: var(--text-primary, #333);
  margin: 0 0 10px 0;
}

.editor-toolbar {
  display: flex;
  gap: 10px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}

.editor-actions {
  display: flex;
  gap: 10px;
  margin-top: 10px;
  flex-wrap: wrap;
}

.sql-results {
  margin-top: 20px;
}

.sql-results h4 {
  color: var(--text-primary, #333);
  margin: 0 0 15px 0;
}

.error-display {
  background: var(--error-light, #ffe6e6);
  color: var(--error-color, #721c24);
  padding: 15px;
  border-radius: 6px;
  border: 1px solid var(--error-color, #e74c3c);
}

.results-table {
  background: var(--bg-secondary, white);
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--border-color, #ddd);
}

.table-info {
  background: var(--bg-tertiary, #f5f5f5);
  padding: 10px 15px;
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: var(--text-secondary, #666);
}

.table-container {
  max-height: 400px;
  overflow: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
}

thead th {
  background: var(--bg-tertiary, #f8f9fa);
  color: var(--text-primary, #333);
  font-weight: bold;
  padding: 12px;
  text-align: left;
  border-bottom: 2px solid var(--border-color, #dee2e6);
  position: sticky;
  top: 0;
}

tbody td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border-color, #e0e0e0);
  color: var(--text-primary, #333);
  font-size: 13px;
}

tbody tr:hover {
  background: var(--bg-hover, #f8f9fa);
}

/* File storage styles */
.file-editor {
  margin-top: 20px;
}

.file-editor h4 {
  color: var(--text-primary, #333);
  margin: 0 0 10px 0;
}

.editor-toolbar {
  display: flex;
  gap: 10px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}

.file-info {
  margin-top: 20px;
}

.file-info h4 {
  color: var(--text-primary, #333);
  margin: 0 0 15px 0;
}

.file-details {
  background: var(--bg-tertiary, #f5f5f5);
  border-radius: 6px;
  padding: 15px;
}

.info-grid {
  display: grid;
  gap: 10px;
}

.info-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.label {
  font-weight: bold;
  color: var(--text-primary, #333);
}

.value {
  color: var(--text-secondary, #666);
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 13px;
}

.no-file {
  color: var(--text-muted, #999);
  font-style: italic;
  text-align: center;
  padding: 20px;
}

/* Cache styles */
.cache-display {
  margin-top: 20px;
}

.cache-stats {
  margin-bottom: 20px;
}

.stat-card {
  background: var(--bg-secondary, white);
  border-radius: 8px;
  padding: 20px;
  border: 1px solid var(--border-color, #ddd);
}

.stat-card h5 {
  color: var(--text-primary, #333);
  margin: 0 0 15px 0;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 15px;
}

.stat-item {
  text-align: center;
}

.stat-label {
  display: block;
  color: var(--text-secondary, #666);
  font-size: 12px;
  margin-bottom: 5px;
}

.stat-value {
  display: block;
  color: var(--text-primary, #333);
  font-size: 18px;
  font-weight: bold;
}

/* Sync styles */
.sync-display {
  margin-top: 20px;
}

.sync-status {
  background: var(--bg-tertiary, #f5f5f5);
  border-radius: 6px;
  padding: 15px;
  margin-bottom: 20px;
}

.status-indicator {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.status-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}

.status-dot.connected {
  background: var(--success-color, #2ecc71);
  animation: pulse 2s infinite;
}

.status-dot.disconnected {
  background: var(--error-color, #e74c3c);
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

.status-text {
  color: var(--text-primary, #333);
  font-weight: 500;
}

.last-sync {
  color: var(--text-secondary, #666);
  font-size: 13px;
}

.sync-conflicts {
  margin-bottom: 20px;
}

.sync-conflicts h4 {
  color: var(--text-primary, #333);
  margin: 0 0 15px 0;
}

.conflict-item {
  background: var(--warning-light, #fff4e6);
  border: 1px solid var(--warning-color, #f39c12);
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 15px;
}

.conflict-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
}

.conflict-key {
  font-weight: bold;
  color: var(--text-primary, #333);
}

.conflict-type {
  background: var(--warning-color, #f39c12);
  color: var(--text-inverse, white);
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 12px;
}

.conflict-data {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 15px;
  margin-bottom: 15px;
}

.local-data, .remote-data {
  background: var(--bg-secondary, white);
  border-radius: 6px;
  padding: 10px;
}

.local-data h5, .remote-data h5 {
  color: var(--text-primary, #333);
  margin: 0 0 10px 0;
  font-size: 13px;
}

.local-data pre, .remote-data pre {
  margin: 0;
  font-size: 11px;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.conflict-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
}

.sync-log {
  margin-top: 20px;
}

.sync-log h4 {
  color: var(--text-primary, #333);
  margin: 0 0 15px 0;
}

.log-container {
  background: var(--bg-secondary, #2c3e50);
  border-radius: 6px;
  padding: 15px;
  max-height: 200px;
  overflow-y: auto;
  color: var(--text-primary, white);
}

.log-item {
  display: flex;
  gap: 15px;
  margin-bottom: 10px;
  font-size: 12px;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}

.log-item:last-child {
  margin-bottom: 0;
}

.log-time {
  color: var(--text-muted, #95a5a6);
  min-width: 80px;
}

.log-type {
  min-width: 60px;
  font-weight: bold;
}

.log-item.info .log-type { color: var(--info-color, #3498db); }
.log-item.success .log-type { color: var(--success-color, #2ecc71); }
.log-item.warning .log-type { color: var(--warning-color, #f39c12); }
.log-item.error .log-type { color: var(--error-color, #e74c3c); }

.log-message {
  flex: 1;
  color: var(--text-primary, #ecf0f1);
}

/* 消息提示 */
.message {
  position: fixed;
  top: 20px;
  right: 20px;
  padding: 15px 20px;
  border-radius: 8px;
  color: var(--text-inverse, white);
  font-weight: 600;
  z-index: 1000;
  animation: slideIn 0.3s ease;
  max-width: 400px;
  box-shadow: var(--shadow, 0 4px 12px rgba(0, 0, 0, 0.15));
}

.message.success {
  background: var(--success-color, #28a745);
}

.message.error {
  background: var(--error-color, #dc3545);
}

.message.warning {
  background: var(--warning-color, #ffc107);
  color: var(--text-primary, #333);
}

.message.info {
  background: var(--info-color, #17a2b8);
}

@keyframes slideIn {
  from {
    transform: translateX(100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .storage-features-page {
    padding: 15px;
  }
  
  .form-row {
    flex-direction: column;
    align-items: stretch;
  }
  
  .btn, .storage-input, .idb-input, .cache-input, .server-input, .filename-input, .db-path-input,
  .store-select, .format-select, .strategy-select {
    width: 100%;
  }
  
  .storage-item, .data-item, .cache-item {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  
  .storage-tabs {
    flex-direction: column;
  }
  
  .stat-grid {
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  }
  
  .conflict-data {
    grid-template-columns: 1fr;
  }
  
  .editor-toolbar, .editor-actions {
    flex-direction: column;
  }
}
</style>

